搜索算法
如果给出一个序列,要求在这个序列中寻找一些元素,那你会怎么做呢?如果允许一些预先操作,你又会怎么做,使得你的方法稳定、高效?
第一种方法是顺序搜索。顺序搜索,就是从某个元素开始,按某个顺序,遍历整个序列,如果找到,则返回找到,反之返回找不到。这种方法的优点,第一是简便,第二是通用。这种方法地球人都能想到,而且在不允许任何预先处理的情况下使用,这是唯一的办法。
样例代码给出如下(注:仅给出核心部分,已过测试)
const int MaxLen=10001;
int array[MaxLen];
bool sequential_search(const int& begin,const int& end,const int& value){
for (int i=begin;i<end;++i){
if (array[i]==value){
return true;
}
}
return false;
}
很简单就可以看出其的时间复杂度为O(n)。
第二种方法是二分查找。这种方法需要排序的预先操作,比如给出一个从小到大的排序好的序列S,一个元素K,在这个序列S中以二分查找的形式,查找这个元素K,具体过程可以概括为:
1.找出序列S的中点的元素E,E将整个序列S分成前半部与后半部两部分;
2.如果K=E,则返回找到;
3.如果K<E,则在前半部递归这个过程予以查找;
4.如果K>E,则在后半部递归这个过程予以查找;
5.如果查找都没有成功,则返回找不到。
根据分析,每层的时间复杂度为O(1),一共有log2n层。所以,可以看出整的时间复杂度是为O(log2n)。但是二分查找有一个显著的缺点:当寻找次数过小时,预先的排序操作会成为一个巨大的包袱,当然,保证的输入除外。如果查找的次数太小,比如说只有一两次,那最快的快速排序的排序速度也只有O(nlog2n),总的来说是O(log2n+log2n),远远大于O(n)的线性时间复杂度。不过二分查找的最大优势还是在的,一般而言,二分搜索的效率还是很高的。const int MaxLen=10001;
int array[MaxLen];
int binary_search(int begin,int end,int value){
if (array[begin]!=value && begin==end){
return -1;
}
if (array[begin]==value && begin==end){
return begin;
}
int mid=(begin+end)/2;
if (array[mid]==value){
return mid;
}
if (array[mid]<value){
return binary_search(begin,mid-1,value);
}
if (array[mid]>value){
return binary_search(mid+1,end,value);
}
}
unsigned int ELFhash(char *key)
{
unsigned long h=0;
while(*key)
{
h=(h<<4)+*key++;
unsigned long g=h&0Xf0000000L;
if(g) h^=g>>24;
h&=~g;
}
return h%MOD;
}
unsigned int BKDRHash(char *key){
unsigned int seed=131;
unsigned int hash=0;
while(*key)
{
hash = hash * seed + (*key++);
}
return hash%MOD;
}